#include "otabase.h"

quint32 crc32Table[256];

OTABase::OTABase()
{
    initCRC32Table();
}

OTABase::~OTABase()
{

}

void OTABase::initCRC32Table()
{
    quint32 c;
    for (size_t i = 0; i < 256; ++i) {
        c = (quint32)i;
        for (int j = 0; j < 8; ++j) {
            c = (c & 1)? (c >> 1) ^ POLYNOMIAL : (c >> 1);
        }
        crc32Table[i] = c;
    }
}

quint32 OTABase::CRC32(QByteArray &byteArr)
{
    quint32 crc = 0xFFFFFFFF;
    for (int i = 0; i < byteArr.size() && i < 11; ++i) {
        crc = crc32Table[(crc ^ byteArr.at(i)) & 0xFF] ^ (crc >> 8);
    }
    uint32_t cla_crc = ~crc;
    byteArr[13] = (cla_crc >> 24)&0xff;
    byteArr[14] = (cla_crc >> 16)&0xff;
    byteArr[15] = (cla_crc >> 8)&0xff;
    byteArr[16] = cla_crc&0xff;
    return ~crc;
}

quint32 OTABase::CRC32(const void *data, size_t size)
{
    uint32_t crc = 0xFFFFFFFF;
    const uint8_t *bytes = (const uint8_t*)data;
    for (size_t i = 0; i < size; ++i) {
        crc = crc32Table[(crc ^ bytes[i]) & 0xFF] ^ (crc >> 8);
    }
    return ~crc;
}

quint32 OTABase::CRC32Only(QByteArray &byteArr)
{
    quint32 crc = 0xFFFFFFFF;
    for (int i = 0; i < byteArr.size(); ++i) {
        crc = crc32Table[(crc ^ byteArr.at(i)) & 0xFF] ^ (crc >> 8);
    }
    return ~crc;
}

quint16 OTABase::sumCheck(QByteArray &byteArr)
{
    uint16_t checksum = 0;
    for (int i = 0; i < byteArr.size() && i < 11; i++) {
        checksum += (uint8_t)byteArr.at(i);
    }
    byteArr[11] = (checksum >> 8)&0xff;   // 只能用于boot pack 校验
    byteArr[12] = checksum&0xff;
    return checksum;
}

quint16 OTABase::sumCheckOnly(QByteArray &byteArr)
{
    uint16_t checksum = 0;
    for (int i = 0; i < byteArr.size(); i++) {
        checksum += (uint8_t)byteArr.at(i);
    }
    return checksum;
}

quint16 OTABase::sumCheck(const void *data, size_t length)
{
    quint16 checksum = 0;
    const quint8 *bytes = (const quint8*)data;
    for (size_t i = 0; i < length; i++) {
        checksum += bytes[i];
    }
    return checksum;
}

void OTABase::createHostPackage(QByteArray &byteArr)
{
    byteArr.resize(OTA_PACK_LEN);
    byteArr[0] = (HOST_ID >> 8)&0xff;
    byteArr[1] = HOST_ID&0xff;
}

void OTABase::createHostPackage(QByteArray &byteArr,
                                quint8 data_len,
                                OTA::OTA_func func)
{
    byteArr.resize(OTA_PACK_LEN);
    byteArr[0] = (HOST_ID >> 8)&0xff;
    byteArr[1] = HOST_ID&0xff;
    byteArr[2] = data_len; // 长度
    byteArr[3] = func;  // 功能码
}
